<template>
  <div class="upload-container" @drop="handleDrop" ref="container" @dragover="handleDragOver">
    <input ref="upload" type="file" multiple style="display: none" @change="handleUpload">
    <div class="empty" v-if="!fileList.length" @click="handleClick('replace')">
      <a-icon class="icon" type="cloud-upload"/>
      <div class="text">将图片拖拽至此处，或 <span style="color: blueviolet">点击上传</span></div>
    </div>
    <div class="not-empty" v-else>
      <div class="card" v-for="(item, index) in fileList" :key="item.id">
        <img alt="" :src="item.base64Url">
        <div class="mask">
          <a-icon type="eye" @click="handlePreview(item)"/>
          <a-icon type="delete" @click="handleDelete(index)"/>
        </div>
      </div>
      <div class="card" style="cursor: pointer" @click="handleClick('plus')" v-if="fileList.length < limit">
        <a-icon type="plus" style="font-size: 54px;"/>
      </div>
    </div>
    <a-modal :footer="null" :visible="previewVisible" :title="previewTitle" @cancel="handleCancel">
      <img alt="example" style="width: 100%" :src="previewImage"/>
    </a-modal>
  </div>
</template>

<script>
import {nanoid} from 'nanoid'

export default {
  data() {
    return {
      fileList: [],
      type: '',
      previewVisible: false,
      previewTitle: '',
      previewImage: ''
    }
  },
  props: ['limit'],
  methods: {
    async handleUpload(e) {
      if (this.type === 'replace') {
        this.fileList = []
        let files = Array.from(e.target.files)
        if (files.length > this.limit) {
          this.$message.warning(`当前限制选择 ${this.limit} 个文件，本次选择了 ${files.length} 个文件`)
          return
        }
        const promise = files.map(async item => {
          item.base64Url = await this.getBase64(item)
        })
        await Promise.all(promise)
        files.forEach(item => {
          this.fileList.push({
            imgSize: this.getSize(item.size),
            base64Url: item.base64Url,
            name: item.name,
            id: nanoid()
          })
        })
      } else {
        if (this.fileList.length < this.limit) {
          let files = Array.from(e.target.files)
          if ((files.length + this.fileList.length) > this.limit) {
            this.$message.warning(`当前限制选择 ${this.limit} 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + this.fileList.length} 个文件`)
            return
          }
          const promise = files.map(async item => {
            item.base64Url = await this.getBase64(item)
          })
          await Promise.all(promise)
          files.forEach(item => {
            this.fileList.push({
              imgSize: this.getSize(item.size),
              base64Url: item.base64Url,
              name: item.name,
              id: nanoid()
            })
          })
        }
      }
    },
    handleClick(type) {
      this.$refs['upload'].click()
      this.type = type
    },
    getBase64(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = () => resolve(reader.result)
        reader.onerror = error => reject(error)
      })
    },
    getSize(size) {
      if (size < 0.1 * 1024) {
        size = size.toFixed(2) + "B";
      } else if (size < 1 * 1024 * 1024) {
        size = (size / 1024).toFixed(2) + "KB";
      } else if (size < 0.1 * 1024 * 1024 * 1024) {
        size = (size / (1024 * 1024)).toFixed(2) + "MB";
      } else {
        size = (size / (1024 * 1024 * 1024)).toFixed(2) + "GB";
      }
      let sizeStr = size + "",
          index = sizeStr.indexOf("."),
          dou = sizeStr.substring(index + 1, 2);
      if (dou === "00") return sizeStr.substring(0, index) + sizeStr.substring(index + 3, 2);
      return size;
    },
    handleCancel() {
      this.previewVisible = false
    },
    handlePreview(item) {
      this.previewTitle = item.name
      this.previewImage = item.base64Url
      this.previewVisible = true
    },
    handleDelete(index) {
      this.fileList.splice(index, 1)
    },
    async handleDrop(e) {
      // console.log(e.dataTransfer.files)
      e.stopPropagation()
      e.preventDefault()
      this.fileList = []
      let files = Array.from(e.dataTransfer.files)
      if (files.length > this.limit) {
        this.$message.warning(`当前限制选择 ${this.limit} 个文件，本次选择了 ${files.length} 个文件`)
        return
      }
      const promise = files.map(async item => {
        item.base64Url = await this.getBase64(item)
      })
      await Promise.all(promise)
      files.forEach(item => {
        this.fileList.push({
          imgSize: this.getSize(item.size),
          base64Url: item.base64Url,
          name: item.name,
          id: nanoid()
        })
      })
    },
    handleDragOver(e) {
      e.stopPropagation()
      e.preventDefault()
    }
  },
  watch: {
    fileList: function (newVal, oldVal) {
      this.$emit('onChange', newVal)
    }
  },

}
</script>

<style lang="less" scoped>
.upload-container {
  width: 800px;
  min-height: 200px;
  height: fit-content;
  border: 1px dashed skyblue;

  .empty {
    width: 100%;
    min-height: 200px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    cursor: pointer;

    .icon {
      font-size: 64px;
      color: blueviolet;
    }

    .text {
      margin-top: 10px;
    }
  }

  .not-empty {
    width: fit-content;
    min-height: 200px;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    padding: 0 20px;

    .card {
      width: 120px;
      height: 120px;
      border-radius: 5px;
      border: 1px dashed skyblue;
      margin: 10px 10px;
      display: flex;
      justify-content: center;
      align-items: center;
      background: #fafafa;
      transition: all .2s;

      .mask {
        opacity: 0;
        position: absolute;
        width: 120px;
        height: 120px;
        z-index: 10;
        background: rgba(4, 20, 41, 0.8);
        display: flex;
        justify-content: center;
        align-items: center;

        .anticon {
          font-size: 32px;
          color: #fff;
          font-weight: 600;
          margin: 0 10px;
          cursor: pointer;
        }
      }

      img {
        width: auto;
        height: auto;
        max-height: 100%;
        max-width: 100%;
      }
    }

    .card:hover {
      .mask {
        opacity: 1;
        transition: opacity .2s;
      }
    }
  }
}
</style>
